import {useEffect, useState} from "react";
import {getScene, getWidgets} from "../services";
import service from '../services/request/components';
import {IComponent, IComponentType} from "@bastet/widgets";
import { widgets as testWidgetNames } from '../widgets.json';
import {assign} from "@bastet/utils";
import uuid from "uuid/v4";

const localWidgetObject: Map<string, Promise<any>> = (import.meta as any).glob('/src/widget/**/index.tsx');

export function resizeCustom(settings: IComponent = {} as IComponent) {
  const name = settings.name
  if (!settings.children) settings.children = []
  // console.log('resizeCustom: => ', name)
  switch (name) {
    case 'GRID': {
      if (settings.config) {
        const { column = 1, row = 1, type } = settings.config
        if (type === 'WIDGET:GRID') {
          const gridRow = new Array(row).fill(null)
          const gridColumn = new Array(column).fill(null)
          // console.log('children', settings.children)
          settings.children = gridRow.map((_, row) => {
            return {
              name: `GRID-ROW`,
              type: IComponentType.DRAG,
              renderProps: { className: 'row ' },
              children: gridColumn.map((_, col) => {
                const children = settings.children?.[row]?.children?.[col]?.children || []
                // console.log('children', children)
                return {
                  name: 'GRID-COLUMN',
                  type: IComponentType.DROP,
                  renderProps: { className: `col-${24 / column} ` },
                  children: children.map(resizeCustom)
                }
              })
            }
          })
        }
      }
    }
  }

  return settings
}

/**
 * 加载本地组件
 */
const localWidgetMap = new Map()
export async function loadLocalWidgets () {
  if (localWidgetMap.size) return localWidgetMap

  for (let [path, localWidget] of Object.entries(localWidgetObject)) {
    const widget = await localWidget();
    if (widget) {
      path = path.replace('/index.tsx', '')
      const widgetName = path.split('/').pop()
      const upperCaseName = widgetName!.toLocaleUpperCase();

      widget.settings.name = upperCaseName;
      localWidgetMap.set(upperCaseName, {
        ...widget,
        settings: resizeCustom(widget.settings)
      });
      // console.log('widgets: => ', upperCaseName, widget)
      // console.log('localWidgetMap: => ', localWidgetMap)
    }
  }
  return localWidgetMap;
}


function resetGrid (grid: IComponent, callback: (col: any, index: number, idx: number) => void) {
  if (grid.children) {
    grid.children = grid.children.map((row, index) => {
      if (row.children) {
        row.children.map((col, idx) => callback(col, index, idx))
      }
      return row
    })
  }
  return grid
}


/**
 * 重构组件参数
 *
 * @param localSettings
 * @param remoteSettings
 */
function resetSettings (localSettings: IComponent, remoteSettings: IComponent) {
  const name = localSettings.name!.toLocaleUpperCase()
  const settings: IComponent = localSettings

  switch (name) {
    case 'GRID': {
      return resetGrid(settings, (col, index, idx) => {
        const children = remoteSettings?.children?.[index]?.children?.[idx]?.children  || [];
        if (children && Array.isArray(children) && children.length) {
          col.children = children.map(child => resetSettings(child, remoteSettings))
        }
        return col;
      });
    }
    default: return settings
  }
}

/**
 * 重构 Scene 组件参数
 *
 * @param localSettings
 * @param remoteSettings
 */
function resetSceneSettings (localSettings: IComponent, remoteSettings: IComponent) {
  const name = localSettings.name!.toLocaleUpperCase()
  const settings: IComponent = localSettings

  if (!settings.id) settings.id = uuid()
  switch (name) {
    case 'GRID': {
      return resetGrid(settings, (col, index, idx) => {
        const children = remoteSettings?.children?.[index]?.children?.[idx]?.children  || [];
        if (children && Array.isArray(children) && children.length) {
          col.children = children.map(child => resetSceneSettings(child, remoteSettings))
        }
        return col;
      });
    }
    default: return settings
  }
}



export async function testWidthLocalWidget (remoteWidgets: Map<string, {default: any, settings: IComponent}>) {
  const localWidgets = await loadLocalWidgets()

  localWidgets.forEach((local) => {
    const { name } = local.settings
    const remote = remoteWidgets.get(name);

    if (remote && testWidgetNames.includes(name)) {
      remoteWidgets.set(name, {
        ...local,
        settings: resetSettings(local.settings, remote.settings)
      })
    } else {
      // 新开发的组件
      remoteWidgets.set(name, local)
    }
  })

  return remoteWidgets
}

/**
 * 替换 场景中的 组件配置
 * @param remoteWidgets
 */
export async function testSceneWidthLocalWidget (remoteWidgets: IComponent[]) {
  const localWidgetMap = await loadLocalWidgets()

  remoteWidgets.forEach((remote) => {
    const name = remote.name!
    const local = localWidgetMap.get(name);
    if (local && testWidgetNames.includes(name)) {
      Object.assign(remote, resetSceneSettings(local.settings, remote))
    }
    if (!remote.id) remote.id = uuid()
  })

  return remoteWidgets
}

/**
 * 当前场景中用到的所有组件
 *
 * @param widgetData
 */
export async function loadRemoteWidgets(widgetData: IComponent[]) {
  const remoteWidgetMap: Map<string, any> = new Map()
  return Promise.all(
    widgetData
      .map((widget: IComponent) => service.get<string, string>(`/${widget.path}`)
        .then((componentText) => {
          if (componentText && widget.name) {
            // 获取组件名称
            const nameLowerCase = widget.name?.toLocaleLowerCase()
            // 执行组件
            eval(componentText)

            const remoteWidget = (window as any)[`$${nameLowerCase}`];
            remoteWidget.settings.name = widget.name;
            remoteWidget.settings = resizeCustom(remoteWidget.settings);
            remoteWidgetMap.set(widget.name, remoteWidget);
            delete (window as any)[`$${nameLowerCase}`]
            return { name: nameLowerCase, componentText }
          }
        }))
  ).then(() => remoteWidgetMap)
}

/**
 * 获取组件列表
 *
 * @param debug
 */
export function useWidgets (debug?: boolean) {
  const [ widgets, setWidgets ] = useState<Map<string, any>>(new Map)

  useEffect(() => {
    getWidgets().then(async ({ code, data }) => {
      /**
       * 请求下来的 widget
       */
      if (code === 200 && Array.isArray(data)) {
        const remoteWidgets = await loadRemoteWidgets(data)
        if (debug) {
          const widgets = await testWidthLocalWidget(remoteWidgets)
          setWidgets(widgets)
        } else {
          setWidgets(remoteWidgets)
        }
      }
    })
  }, [debug])

  return widgets
}